﻿using System;
using BSDS.Core.Model.Services;
using BSDS.Core.Model.Services.Geocoding;
using BSDS.Core.Model.Services.Jobs;
using BSDS.Core.Model.Services.Jobs.Core;
using BSDS.Core.Model.Services.Uploading;

namespace BSDS.Commands.Commands.Implementation.Jobs
{
    public class WaitJobCommand : CommandBase
    {
        private readonly string jobId;
        private readonly JobRepository repository;
        private readonly GeocodingService geocodingService;
        private readonly UploadService uploadService;
        private readonly DownloadService downloadService;
        private readonly JobService jobService;

        public WaitJobCommand(string jobId, JobRepository repository, GeocodingService geocodingService,
            UploadService uploadService, DownloadService downloadService, JobService jobService)
        {
            this.jobId = jobId;
            this.repository = repository;
            this.geocodingService = geocodingService;
            this.uploadService = uploadService;
            this.downloadService = downloadService;
            this.jobService = jobService;
        }

        public override CommandResult Execute(ExecutionContext context)
        {
            if (repository.Exists(jobId, GeocodeJob.TypeName))
            {
                ReturnToGeocoding(repository.Get<GeocodeJob>(jobId), context);
            }
            else if (repository.Exists(jobId, UploadJob.TypeName))
            {
                ReturnToUploading(repository.Get<UploadJob>(jobId));
            }
            else if (repository.Exists(jobId, DownloadJob.TypeName))
            {
                ReturnToDownloading(repository.Get<DownloadJob>(jobId), context);
            }
            else
            {
                Console.WriteLine(string.Format("No job with such id exists {0}.", jobId));
            }

            return CommandResult.Success();
        }

        private void ReturnToDownloading(DownloadJob job, ExecutionContext context)
        {
            var state = jobService.WaitForEnd(job.Id, downloadService);

            if (state.Status == JobStatus.Completed)
            {
                var commandText = job.Command + " /remsumeCompletedJob=" + job.Id;

                context.Dispatcher.Dispatch(CommandInfo.Parse(commandText));
            }
        }

        private void ReturnToUploading(UploadJob job)
        {
            jobService.WaitForEnd(job.Id, uploadService);

            var detailsMessage = jobService.GetLongDetailsMessage(job.Id);

            Console.WriteLine(detailsMessage);
        }

        private void ReturnToGeocoding(GeocodeJob job, ExecutionContext context)
        {
            var state = jobService.WaitForEnd(job.Id, geocodingService);

            if (state.Status == JobStatus.Completed)
            {
                var commandText = job.Command + " /resumeCompletedJob=" + job.Id;

                context.Dispatcher.Dispatch(CommandInfo.Parse(commandText));
            }
        }
    }
}